/**
 * 
 */
package tp8.tsh.commands.impl;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.Formatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import tp8.tsh.cli.CurrentDirectory;
import tp8.tsh.cli.TSHOutput;
import tp8.tsh.commands.intf.Command;
import tp8.tsh.exc.TSHException;

/**
 * @author tpana
 * 
 */
public class ListContents implements Command {

	private TSHOutput out;

	private static final int UNIT_KB = 1024;
	private static final int UNIT_MB = UNIT_KB * UNIT_KB;
	private static final int UNIT_GB = UNIT_KB * UNIT_KB * UNIT_KB;

	/*
	 * (non-Javadoc)
	 * 
	 * @see tp8.tsh.commands.intf.Command#setTSHOutput(tp8.tsh.cli.TSHOutput)
	 */
	@Override
	public void setTSHOutput(TSHOutput tshOutput) {
		this.out = tshOutput;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see tp8.tsh.commands.intf.Command#getName()
	 */
	@Override
	public String getName() {
		return "ls";
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see tp8.tsh.commands.intf.Command#getVersion()
	 */
	@Override
	public String getVersion() {
		return "1.0";
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see tp8.tsh.commands.intf.Command#getAliasMap()
	 */
	@Override
	public Map<String, String> getAliasMap() {
		Map<String, String> aliasMap = new HashMap<String, String>();
		aliasMap.put("ls", null);
		aliasMap.put("dir", null);
		return aliasMap;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see tp8.tsh.commands.intf.Command#getArgsRegEx()
	 */
	@Override
	public List<String> getArgsRegEx() {
		List<String> argsList = new ArrayList<String>();
		return argsList;
	}

	@Override
	public void execute(String[] args, CurrentDirectory curDir,
			Map<String, String> envVars) throws TSHException {
		File[] contents = curDir.listAll();

		Arrays.sort(contents, new Comparator<File>() {
			@Override
			public int compare(File object1, File object2) {
				int result = 0;

				boolean isDir1 = object1.isDirectory();
				boolean isDir2 = object2.isDirectory();

				if (isDir1 == isDir2) {
					try {
						result = object1.getCanonicalPath().compareTo(
								object2.getCanonicalPath());
					} catch (IOException exc) {
						result = 0;
					}
				} else {
					if (isDir1) {
						result--;
					} else {
						result++;
					}
				}
				return result;
			}
		});

		for (File file : contents) {
			out.println(getLine(file));
		}

	}

	private String getLine(File file) {
		Date date = new Date(file.lastModified());
		SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");

		String size = calculateSize(file.length());
		String lastModified = sdf.format(date);
		String directory = file.isDirectory() ? "D" : " ";
		String hidden = file.isHidden() ? "H" : " ";
		String read = file.canRead() ? "R" : " ";
		String write = file.canWrite() ? "W" : " ";
		String execute = file.canExecute() ? "X" : " ";
		StringBuilder sb = new StringBuilder();
		Formatter formatter = new Formatter(sb);
		formatter.format("%1$-46s %2$6s %3$-19s "
				+ "%4$-1s%5$-1s %6$-1s%7$-1s%8$-1s", file.getName(), size,
				lastModified, directory, hidden, read, write, execute);
		return sb.toString();
	}

	private String calculateSize(long size) {
		String result;
		if (size < UNIT_KB) {
			result = size + "B";
		} else if (size < UNIT_MB) {
			result = (size / UNIT_KB) + "KB";
		} else if (size < UNIT_GB) {
			result = (size / UNIT_MB) + "MB";
		} else {
			result = (size / UNIT_GB) + "GB";
		}
		return result;
	}
}
